package com.lyEducation.services.system;

import com.lyEducation.controllers.dto.system.InsertUpdSysMenuDto;
import com.lyEducation.core.base.SysConstants;
import com.lyEducation.core.base.TreeEntityService.UpDownTreeEntityService;
import com.lyEducation.core.base.TreeEntityService.UpDownTreeEntityServiceImpl;
import com.lyEducation.core.system.SysMenuService;
import com.lyEducation.entities.middle.SysRoleMenuEntity;
import com.lyEducation.entities.system.SysMenuEntity;
import com.lyEducation.entities.system.SysRoleEntity;
import com.lyEducation.repository.system.SysMenuRepository;
import com.lyEducation.repository.system.SysRoleRepository;
import com.lyEducation.repository.system.SysUserRepository;
import com.lyEducation.security.config.SecurityPrincipalContext;
import com.lyEducation.services.base.BaseDateServiceImpl;
import com.lyEducation.util.EntityUtil;
import com.lyEducation.util.StringUtils;
import com.lyEducation.util.controllerUtil.JsonConstans;
import com.lyEducation.util.controllerUtil.JsonResult;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.*;

/** @author eiven */

/** 非顶级权限下的权限菜单只能在当前拥有该菜单的情况下进行给下级权限做菜单增删改操作 */
@Service
public class SysMenuServiceImpl extends BaseDateServiceImpl<SysMenuEntity>
    implements SysMenuService {
  @Autowired private SysMenuRepository sysMenuRepository;

  @Autowired private SysRoleRepository sysRoleRepository;

  @Autowired private SysUserRepository sysUserRepository;

  @Override
  public void delete(String id, HashMap<String, Object> map) {
    // 删除子菜单
    List<SysMenuEntity> sysMenuEntityList = sysMenuRepository.findByFiled("parentId", id);
    for (SysMenuEntity sysMenuEntity : sysMenuEntityList) {
      delete(sysMenuEntity.getId(), map);
    }
    // 删除角色菜单
    String hql =
        "delete from "
            + EntityUtil.getHqlTableName(SysRoleMenuEntity.class)
            + " as rm where rm.menuId =:menuId";
    map.clear();
    map.put("menuId", id);
    sysMenuRepository.deleteByMap(SysRoleMenuEntity.class, hql, map);
    sysMenuRepository.deleteById(id);
  }

  @Override
  public SysMenuEntity findMenuRoleById(String menuId) {
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("id", menuId);
    String sql = "select m.* from sys_menu m where m.id=:id";

    SysMenuEntity menu = sysMenuRepository.findById(SysMenuEntity.class, menuId);
    if (menu == null) {
      return null;
    }
    sql = "SELECT * FROM sys_role_menu rm WHERE rm.menuId=:menuId";

    paramMap.clear();
    paramMap.put("menuId", menuId);
    // 菜单角色权限中间表
    List<SysRoleMenuEntity> roleMenuList =
        sysMenuRepository.findByNativeQuery(
            sql, paramMap, Transformers.aliasToBean(SysRoleMenuEntity.class));

    if (roleMenuList == null || roleMenuList.size() == 0) {
      return menu;
    }
    sql = "SELECT * FROM sys_role r WHERE r.id in (:roleIdList)";
    List<String> roleIdList = new ArrayList<>();
    for (SysRoleMenuEntity roleMenu : roleMenuList) {
      roleIdList.add(roleMenu.getRoleId());
    }
    paramMap.clear();
    paramMap.put("roleIdList", roleIdList);
    // 所有菜单的拥有的权限
    List<SysRoleEntity> roleList =
        sysMenuRepository.findByNativeQuery(
            sql, paramMap, Transformers.aliasToBean(SysRoleEntity.class));
    if (roleList == null || roleList.size() == 0) {
      return menu;
    }
    menu.setSysRoleList(roleList);
    return menu;
  }
  // 将本级权限的资源分发给下一级，超级管理员可以任意分发资源
  @Override
  public JsonResult insertUpdMenu(InsertUpdSysMenuDto sysMenuDto) {
    JsonResult jsonResult = null;
    SysMenuEntity menu = null;
    String url = sysMenuDto.getUrl();
    String menuName = sysMenuDto.getName();
    int sort = sysMenuDto.getSort();
    List<SysMenuEntity> existMenuList = null;
    if (StringUtils.isBlank(url)) {
      return JsonResult.putFail("url不能为空");
    }
    if (StringUtils.isBlank(menuName)) {
      return JsonResult.putFail("菜单名不能为空");
    }
    url = StringUtils.trim(url);
    menuName = StringUtils.trim(menuName);
    LinkedHashMap<String, Object> paramMap = new LinkedHashMap<>();
    List<SysRoleEntity> userRoleList = sysUserRepository.userGetRoleList(null, null);
    // 新建菜单需要最高级权限
    if (StringUtils.isBlank(sysMenuDto.getId())) {
      //新增菜单属性校验
      if (userRoleList.size() != 1 || !SysConstants.PROJECT_ROLE_ADMIN.getValue().equals(userRoleList.get(0).getName())) {
        return JsonResult.putFail("新建菜单失败，权限不足");
      }
      existMenuList = sysMenuRepository.findByFiled("url", url);
      if (existMenuList.size() != 0) {
        return JsonResult.putFail("已经存在该" + url + "菜单，添加失败");
      }
      existMenuList = sysMenuRepository.findByFiled("name", menuName);
      if (existMenuList.size() != 0) {
        return JsonResult.putFail("已经存在菜单名为 ：" + menuName + "的菜单，添加失败");
      }
    } else {//更新菜单属性校验
      menu = sysMenuRepository.findById(sysMenuDto.getId());
      if (menu == null || menu.getIsDelete()) {
        return JsonResult.putFail("更新失败，无该菜单");
      }
      if (!StringUtils.equals(menu.getUrl(), url)) {
        existMenuList = sysMenuRepository.findByFiled("url", url);
        if (existMenuList.size() != 0) {
          return JsonResult.putFail("已经存在该" + url + "菜单，添加失败");
        }
      }
      if (!StringUtils.equals(menu.getName(), menuName)) {
        existMenuList = sysMenuRepository.findByFiled("name", menuName);
        if (existMenuList.size() != 0) {
          return JsonResult.putFail("已经存在菜单名为 ：" + menuName + "的菜单，添加失败");
        }
      }
      jsonResult = JsonResult.putFail("当前登录权限不足无法修改菜单：" + menu.getName());
      for (SysRoleEntity sysRoleEntity : userRoleList) {
        paramMap.clear();
        paramMap.put("menuId", menu.getId());
        paramMap.put("roleId", sysRoleEntity.getId());
        List<SysRoleMenuEntity> sysRoleMenuEntities =
            sysMenuRepository.findByFileds(SysRoleMenuEntity.class, paramMap);
        if (sysRoleMenuEntities.size() == 1) {
          jsonResult = null;
          break;
        }
      }
      if (jsonResult != null) {
        return jsonResult;
      }
    }

    List<String> roleIdList = sysMenuDto.getRoleIdList();

    TreeSet<SysRoleEntity> maxRoleSet = new TreeSet<SysRoleEntity>(
            new Comparator<SysRoleEntity>() {
              @Override
              public int compare(SysRoleEntity o1,SysRoleEntity o2) {
                if (!StringUtils.equals(o1.getParentId(), o2.getParentId())) {
                  throw new RuntimeException("同一级别添加错误");
                }
                if (o1.getId().equals(o2.getId())) {
                  return 0;
                }
                int sort = o1.getSort() - o2.getSort();
                if (sort == 0) {
                  return 1;
                }
                return sort;
              }
            });
    if (roleIdList == null || roleIdList.size() == 0) {
      return JsonResult.putFail("不能传入空权限");
    }
    // 顶级权限向下存储
    jsonResult = checkParamBySaveOrUpdMenu(roleIdList, maxRoleSet, userRoleList);
      if (jsonResult != null) {
        return jsonResult;
      }

    // 处理父级菜单权限
    String parentId = sysMenuDto.getParentId();
    if (menu != null && StringUtils.equals(menu.getId(), parentId)) {
      return JsonResult.putFail("父级菜单不能是子级菜单");
    }
    SysMenuEntity fatherMenu = null;
    // 父级菜单权限
    List<SysRoleMenuEntity> sysRoleMenuEntities = null;
    if (userRoleList.size() == 1 && SysConstants.PROJECT_ROLE_ADMIN.getValue().equals(userRoleList.get(0).getName())) {
      // 超级管理员权限修改需要传入自身权限
      if (!maxRoleSet.iterator().next().getName().equals(SysConstants.PROJECT_ROLE_ADMIN.getValue())) {
        return JsonResult.putFail("参数缺失顶级权限");
      }
      // 子菜单权限不允许有不在父菜单权限内
      if (StringUtils.isNotBlank(parentId)) {
        fatherMenu = sysMenuRepository.findById(parentId);
        if (fatherMenu == null || fatherMenu.getIsDelete()) {
          return JsonResult.putFail("上级菜单不存在");
        }
        // 获取父级菜单所有包括顶级权限
        paramMap.clear();
        paramMap.put("menuId", fatherMenu.getId());
        sysRoleMenuEntities = sysMenuRepository.findByFileds(SysRoleMenuEntity.class, paramMap);
        jsonResult = checkFatherMenuRole(sysRoleMenuEntities, maxRoleSet);
        if (jsonResult != null) {
          return jsonResult;
        }
        jsonResult = menuParentIdSafe(sysRoleMenuEntities, userRoleList);
        if (jsonResult != null) {
          return jsonResult;
        }
      }
    } else {
      // 非超级管理员只能编辑登录权限的下级权限且只能是父级菜单权限范围内的权限
      // 新增菜单权限是否在本菜单上级菜单权限下
      if (StringUtils.isNotBlank(menu.getParentId())) {
        fatherMenu = sysMenuRepository.findById(menu.getParentId());
        // 获取父级菜单所有包括顶级权限
        paramMap.clear();
        paramMap.put("menuId", fatherMenu.getId());
        sysRoleMenuEntities = sysMenuRepository.findByFileds(SysRoleMenuEntity.class, paramMap);
        jsonResult = checkFatherMenuRole(sysRoleMenuEntities, maxRoleSet);
        if (jsonResult != null) {
          return jsonResult;
        }
      }
    }
    // 新建只需上级菜单权限包含下级菜单权限，不存在编辑菜单父级菜单权限修改为新的父级菜单权限下的问题
    // 编辑菜单权限减少所有 菜单上级父类改变 移除菜单原权限包括下级，新增菜单新父级的权限包括所有下级
    if (menu != null) {
      paramMap.clear();
      paramMap.put("menuId", menu.getId());
      List<SysRoleMenuEntity> menuOldRoles =
              sysMenuRepository.findByFileds(SysRoleMenuEntity.class, paramMap);
      List<String> list = null;
      // 去掉不存在于传入权限参数的旧权限
      if (userRoleList.size() == 1 && SysConstants.PROJECT_ROLE_ADMIN.getValue().equals(userRoleList.get(0).getName())) {
        // 权限
        List<SysRoleMenuEntity> menuOldRoleNeedDel = new ArrayList<>();

        removeRoleList(menuOldRoleNeedDel, menuOldRoles, maxRoleSet);

        if (menuOldRoleNeedDel.size() > 0) {
          list = new ArrayList<>();
          for (SysRoleMenuEntity sysRoleMenuEntity : menuOldRoleNeedDel) {
            list.add(sysRoleMenuEntity.getRoleId());
          }
          delMenuRole(list, menu);
        }
      } else {
        // 非超级管理员可添加删除其登录权限的下级权限
        // 获取当前登录权限及其拥有的下级权限
        TreeSet<SysRoleEntity> underUserRoleList = new TreeSet<>();
        for (SysRoleEntity sysRoleEntity : userRoleList) {
          List<SysRoleEntity> sysRoleEntities =
              sysRoleRepository.findByFiled("parentId", sysRoleEntity.getId());
          for (SysRoleEntity sysRoleEntity1 : sysRoleEntities) {
            sysRoleRepository.findTreeRole(sysRoleEntity1);
            underUserRoleList.add(sysRoleEntity1);
          }
        }
        List<SysRoleMenuEntity> needSaveRoleMenu = new ArrayList<>();
        for (SysRoleMenuEntity sysRoleMenuEntity : menuOldRoles) {
          rs(underUserRoleList, sysRoleMenuEntity, needSaveRoleMenu);
        }

        removeRoleListNoParend(needSaveRoleMenu, maxRoleSet);
        list = new ArrayList<>();
        if (needSaveRoleMenu.size() > 0) {
          for (SysRoleMenuEntity sysRoleMenuEntity : needSaveRoleMenu) {
            list.add(sysRoleMenuEntity.getRoleId());
          }
          delMenuRole(list, menu);
        }
      }
    }
    // 超管新建情况下，超管非超管更新情况下parentId没变的情况下包括传空，必须parentMenu全部拥有其传入的menu的权限
    // 上下级权限一致
    if (menu == null) {
      menu = new SysMenuEntity();
      if (fatherMenu != null) {
        menu.setLevel(fatherMenu.getLevel() + 1);
      } else {
        menu.setLevel(0);
      }
    }
    menu.setParentId(parentId);
    menu.setUrl(url);
    menu.setName(menuName);
    menu.setSort(sort);
    if (StringUtils.isNotBlank(menu.getId())) {
      sysMenuRepository.update(menu);
    } else {
      sysMenuRepository.save(menu);
    }
    Timestamp createTime = menu.getCreateTime();
    for (SysRoleEntity maxRole : maxRoleSet) {
      setMenuRole(menu, maxRole, createTime, sysMenuDto.isNeedChildMenuRole());
    }
    return JsonResult.putSuccess();
  }

  private void rs(
          TreeSet<SysRoleEntity> underUserRoleList,
          SysRoleMenuEntity sysRoleMenuEntity,
          List<SysRoleMenuEntity> needSaveRoleMenu) {
    for (SysRoleEntity sysRoleEntity : underUserRoleList) {
      if (sysRoleEntity.getId().equals(sysRoleMenuEntity.getRoleId())) {
        needSaveRoleMenu.add(sysRoleMenuEntity);
        return;
      }
      if (sysRoleEntity.getChildren() != null) {
        rs(sysRoleEntity.getChildren(), sysRoleMenuEntity, needSaveRoleMenu);
      }
    }
  }

  private void setMenuRole(SysMenuEntity menu, SysRoleEntity maxRole, Timestamp createTime, boolean isNeedChildMenuRole) {
    saveRoleMenuByRoleTeeSet(maxRole, menu, createTime);
    Map<String, Object> map = new HashMap<String, Object>();
    if (isNeedChildMenuRole) {
      setChildMenuRole(menu, maxRole, createTime, map);
    }
  }

  private void setChildMenuRole(SysMenuEntity menu, SysRoleEntity maxRole, Timestamp createTime, Map<String, Object> map) {
    map.put("parentId", menu.getId());
    // 其所有的下级菜单都会被添加权限
    String sql =
            "select m.* from "
                    + EntityUtil.getSqlTableName(menu.getClass())
                    + " as m where m.parentId=:parentId";
    List<SysMenuEntity> sysMenuEntities =
            sysMenuRepository.findByNativeQuery(
                    sql, map, Transformers.aliasToBean(SysMenuEntity.class));
    for (SysMenuEntity sysMenuEntity1 : sysMenuEntities) {
      saveRoleMenuByRoleTeeSet(maxRole, sysMenuEntity1, createTime);
      setChildMenuRole(sysMenuEntity1, maxRole, createTime, map);
    }
  }

  private void removeRoleList(
          List<SysRoleMenuEntity> menuOldRoleNeedDel,
          List<SysRoleMenuEntity> menuOldRoles,
          TreeSet<SysRoleEntity> maxRoleSet) {
    for (SysRoleMenuEntity sysRoleMenuEntity : menuOldRoles) {
      boolean flg = removeRoleList(sysRoleMenuEntity, maxRoleSet);
      if (flg == false) {
        menuOldRoleNeedDel.add(sysRoleMenuEntity);
      }
    }
  }

  private boolean removeRoleList(
          SysRoleMenuEntity sysRoleMenuEntity, TreeSet<SysRoleEntity> maxRoleSet) {
    boolean flg = false;
    for (SysRoleEntity newRole : maxRoleSet) {
      if (newRole.getId().equals(sysRoleMenuEntity.getRoleId())) {
        flg = true;
        return flg;
      }
      if (newRole.getChildren().size() > 0) {
        flg = removeRoleList(sysRoleMenuEntity, newRole.getChildren());
        if (flg) {
          return flg;
        }
      }
    }
    return flg;
  }

  private void removeRoleListNoParend(
          List<SysRoleMenuEntity> menuOldRoles, TreeSet<SysRoleEntity> maxRoleSet) {
    Iterator<SysRoleMenuEntity> iterator = menuOldRoles.iterator();
    while (iterator.hasNext()) {
      removeRoleListNoParend(iterator, iterator.next(), maxRoleSet);
    }
  }

  private void removeRoleListNoParend(
          Iterator<SysRoleMenuEntity> iterator,
          SysRoleMenuEntity sysRoleMenuEntity,
          TreeSet<SysRoleEntity> maxRoleSet) {
    for (SysRoleEntity sysRoleEntity : maxRoleSet) {
      if (sysRoleEntity.getId().equals(sysRoleMenuEntity.getRoleId())) {
        iterator.remove();
        return;
      }
      if (sysRoleEntity.getChildren() != null && sysRoleEntity.getChildren().size() > 0) {
        removeRoleListNoParend(iterator, sysRoleMenuEntity, sysRoleEntity.getChildren());
      }
    }
  }

  private void delMenuRole(List<String> roleIdList, SysMenuEntity sysMenuEntity) {
    Map<String, Object> paramMap = new HashMap();
    String hqlSql =
        "delete from "
            + EntityUtil.getHqlTableName(SysRoleMenuEntity.class)
            + " where roleId in(:roleIdList) and menuId=:menuId";

    paramMap.put("roleIdList", roleIdList);
    paramMap.put("menuId", sysMenuEntity.getId());
    sysMenuRepository.deleteByMap(SysRoleMenuEntity.class, hqlSql, paramMap);
    paramMap.clear();
    paramMap.put("parentId", sysMenuEntity.getId());
    hqlSql =
        "select r.* from "
            + EntityUtil.getSqlTableName(SysMenuEntity.class)
            + " as r where r.parentId=:parentId";
    List<SysMenuEntity> sysMenuEntities =
        sysMenuRepository.findByNativeQuery(
            hqlSql, paramMap, Transformers.aliasToBean(SysMenuEntity.class));
    for (SysMenuEntity sysMenuEntity1 : sysMenuEntities) {
      delMenuRole(roleIdList, sysMenuEntity1);
    }
  }

  private JsonResult checkFatherMenuRole(
          List<SysRoleMenuEntity> sysRoleMenuEntities,
          TreeSet<SysRoleEntity> maxRoleSet) {
    SysRoleEntity sysRoleEntity = checkSonFatherRoleSome(maxRoleSet, sysRoleMenuEntities);
    if (sysRoleEntity != null) {
      return JsonResult.putFail("无法添加" + sysRoleEntity.getName() + "权限" + ",父级菜单不存在该权限");
    }
    return null;
  }

  // 新建编辑父子级权限都需一致
  private SysRoleEntity checkSonFatherRoleSome(
          TreeSet<SysRoleEntity> maxRoleSet, List<SysRoleMenuEntity> sysRoleMenuEntities) {
    for (SysRoleEntity sysRoleEntity : maxRoleSet) {
      SysRoleEntity res = sysRoleEntity;
      sysRoleMenuEntities:
      for (SysRoleMenuEntity roleMenu : sysRoleMenuEntities) {
        if (roleMenu.getRoleId().equals(sysRoleEntity.getId())) {
          res = null;
          break sysRoleMenuEntities;
        }
      }
      if (res != null) {
        return res;
      }
      TreeSet<SysRoleEntity> sysRoleEntities = sysRoleEntity.getChildren();
      if (sysRoleEntities != null && sysRoleEntities.size() > 0) {
        SysRoleEntity sysRoleEntity2 = checkSonFatherRoleSome(sysRoleEntities, sysRoleMenuEntities);
        if (sysRoleEntity2 != null) {
          return sysRoleEntity2;
        }
      }
    }
    return null;
  }
  /**
   * 权限上下级别排序
   *
   * @param fatherRole
   * @param roleList
   */
  public void setChilentRole(SysRoleEntity fatherRole, List<SysRoleEntity> roleList) {
    if (fatherRole.getChildren() == null) {
      fatherRole.setChildren(null);
    }
    //    Iterator<SysRoleEntity> it = roleList.iterator();
    //    while (it.hasNext()) {
    //      SysRoleEntity x = it.next();
    //      if (x.equals("del")) {
    //        it.remove();
    //      }
    //    }
    for (SysRoleEntity role : roleList) {
      if (fatherRole.getId().equals(role.getParentId())) {
        fatherRole.getChildren().add(role);
      }
    }
    if (fatherRole.getChildren().size() == 0) {
      return;
    }
    for (SysRoleEntity nextFatherRole : fatherRole.getChildren()) {
      setChilentRole(nextFatherRole, roleList);
    }
  }

  public void removeRoleTreeSet(
          TreeSet<SysRoleEntity> roleTreeSet, TreeSet<SysRoleEntity> chilendRoleTreeSet) {
    if (chilendRoleTreeSet.size() == 0) {
      return;
    }
    roleTreeSet.remove(chilendRoleTreeSet);
    for (SysRoleEntity fatherRole : chilendRoleTreeSet) {
      removeRoleTreeSet(roleTreeSet, fatherRole.getChildren());
    }
  }

  public void saveRoleMenuByRoleTeeSet(
      SysRoleEntity roleParent, SysMenuEntity sysMenuEntity, Timestamp createTime) {
    if (sysMenuRepository.findMiddleTable(
            SysRoleMenuEntity.class, "menuId", sysMenuEntity.getId(), "roleId", roleParent.getId())
        == null) {
      addRoleMenu(sysMenuEntity.getId(), roleParent.getId(), createTime);
    }
    Set<SysRoleEntity> childRoles = roleParent.getChildren();
    if (childRoles.size() > 0) {
      for (SysRoleEntity chiledRole : childRoles) {
        saveRoleMenuByRoleTeeSet(chiledRole, sysMenuEntity, createTime);
      }
    }
  }

  private JsonResult checkParamBySaveOrUpdMenu(
          List roleIdList, TreeSet<SysRoleEntity> maxRoleSet, List<SysRoleEntity> userRoleList) {
    Map<String, Object> paramMap = new HashMap();
    paramMap.put("roleIdList", roleIdList);
    List<SysRoleEntity> roleList = sysRoleRepository.findRolesByRoleIdList(paramMap);
    // 指定的权限必须已经存在 roleList.size() == roleIdParamList.size()
    //    判断数量做唯一检验
    if (roleList.size() != roleIdList.size()) {
      return JsonResult.putFail(JsonConstans.ERR_NOTVALID_AUTH);
    }

    //        1.将权限进行树形结构排序
    //        2.
    //          2.1 如果当前账号权限是0则顶级权限是0
    //          2.2 如果不是则检验顶级权限是否是当前所在登陆者的其中一个权限下一级如果不是，则是非法操作，
    //          树形结构排序完毕检验是否有额外没有进行排序的权限并且不是账号顶级权限的下一级如果有则是非法操作
    // 超级管理员修改或新建都需要加进maxRoleSet
    SysRoleEntity adminRole = userRoleList.get(0);
    if (userRoleList.size() == 1 && adminRole.getName().equals(SysConstants.PROJECT_ROLE_ADMIN.getValue())) {
      for (SysRoleEntity role : roleList) {
        if (adminRole.getId().equals(role.getId())) {
          maxRoleSet.add(role);
          break;
        }
      }
    } else {
      // 非超级管理员权限添加限制为其登录权限的下级
      underUserRole:
      for (SysRoleEntity role : roleList) {
        for (SysRoleEntity userRole : userRoleList) {
          if (userRole.getId().equals(role.getParentId())) {
            maxRoleSet.add(role);
            continue underUserRole;
          }
        }
      }
    }
    if (maxRoleSet.size() == 0) {
      return JsonResult.putFail(JsonConstans.ERR_NOTVALID_AUTH);
    }
    // 对添加的最高权限进行上下级添加下级权限
    for (SysRoleEntity maxRole : maxRoleSet) {
      setChilentRole(maxRole, roleList);
    }
    //        检测roleList是否有不在树形权限内的权限如果有则是非法操作
    for (SysRoleEntity maxRole : maxRoleSet) {
      roleList.remove(maxRole);
      roleListRemoveMaxRoleChild(maxRole, roleList);
    }
    if (roleList.size() != 0) {
      return JsonResult.putFail(JsonConstans.ERR_NOTVALID_AUTH);
    }
    // 除了登陆者权限是0，其他下级无论权限指定的是当前登录者下一级哪一级，都是需要上级存在该菜单
    // 指定的权限最高必须在当前登录者权限的下一级，如果是0超级管理员级别则可以指定本级权限
    // 如果不是超级管理员登录 需要检验树形权限的树根顶级权限的父级权限是否有该资源
    // 如果没有则是非法操作
    return null;
  }

  public void roleListRemoveMaxRoleChild(SysRoleEntity maxRole, List<SysRoleEntity> roleList) {
    Set<SysRoleEntity> chilendSet = maxRole.getChildren();
    if (chilendSet.size() != 0) {
      for (SysRoleEntity role : chilendSet) {
        roleList.remove(role);
        roleListRemoveMaxRoleChild(role, roleList);
      }
    }
  }

  private void deleteRoleMenuByRoleTree(String roleId, String menuId) {
    // 关联表删除没有的话则下一级别权限也是没有直接返回
    if (sysMenuRepository.delMiddleTable(
        SysRoleMenuEntity.class, "roleId", roleId, "menuId", menuId)) {
      List<SysRoleEntity> childRoleList =
          sysMenuRepository.findByFiled(SysRoleEntity.class, "parentId", roleId);
      for (SysRoleEntity parentRole : childRoleList) {
        deleteRoleMenuByRoleTree(roleId, menuId);
      }
    }
  }

  /**
   * 添加权限菜单中间表
   *
   * @param menuId
   * @param roleId
   * @param createTime
   */
  private void addRoleMenu(String menuId, String roleId, Timestamp createTime) {
    SysRoleMenuEntity rm = new SysRoleMenuEntity();
    rm.setMenuId(menuId);
    rm.setRoleId(roleId);
    rm.setCreateTime(createTime);
    sysMenuRepository.save(rm);
  }

  /**
   * 更新菜单权限 添加菜单新权限删除不需要的权限，传入的权限集合同一级别与查询出的集合比较，删除查询出的集合多余的权限
   *
   * @param underMaxRole
   * @param menuId
   * @param createTime
   */
  private void addNewDelNotNeedRoleMenu(
      SysRoleEntity underMaxRole, String menuId, Timestamp createTime) {
    TreeSet<SysRoleEntity> underMaxRoleChildRoleSet = underMaxRole.getChildren();
    if (underMaxRoleChildRoleSet.size() != 0) {
      List<SysRoleEntity> allChildRoleList =
          sysRoleRepository.findByFiled("parentId", underMaxRole.getId());
      // 移除掉需要的权限剩下的都是无效权限全部删掉
      allChildRoleList.removeAll(underMaxRoleChildRoleSet);
      if (allChildRoleList.size() != 0) {
        for (SysRoleEntity role : allChildRoleList) {
          sysMenuRepository.delMiddleTable(
              SysRoleMenuEntity.class, "roleId", role.getId(), "menuId", menuId);
        }
      }
      for (SysRoleEntity role : underMaxRoleChildRoleSet) {
        SysRoleMenuEntity roleMenu =
            (SysRoleMenuEntity)
                sysMenuRepository.findMiddleTable(
                    SysRoleMenuEntity.class, "roleId", role.getId(), "menuId", menuId);
        if (roleMenu == null) {
          roleMenu = new SysRoleMenuEntity();
          roleMenu.setRoleId(role.getId());
          roleMenu.setMenuId(menuId);
          roleMenu.setCreateTime(createTime);
          sysMenuRepository.save(roleMenu);
        }
        addNewDelNotNeedRoleMenu(role, menuId, createTime);
      }
    }
  }

  /**
   * parentId限定在登录权限下
   *
   * @param userRoleList
   * @return
   */
  private JsonResult menuParentIdSafe(
      List<SysRoleMenuEntity> sysRoleMenuEntities, List<SysRoleEntity> userRoleList) {
    for (SysRoleMenuEntity sysRoleMenuEntity : sysRoleMenuEntities) {
      for (SysRoleEntity sysRoleEntity : userRoleList) {
        if (sysRoleMenuEntity.getRoleId().equals(sysRoleEntity.getId())) {
          return null;
        }
      }
    }
    return JsonResult.putFail("无权限操作添加的父级菜单");
  }

  @Override
  public TreeSet<SysMenuEntity> findData(Object o) {
    StringBuffer sqlSB = new StringBuffer("from SysRoleEntity where name in (");
    Iterator<? extends GrantedAuthority> grantedAuthorityIterator =
        SecurityPrincipalContext.getUserDetails().getAuthorities().iterator();
    while (grantedAuthorityIterator.hasNext()) {
      sqlSB.append("'").append(grantedAuthorityIterator.next()).append("'");
      if (grantedAuthorityIterator.hasNext()) {
        sqlSB.append(",");
      } else {
        sqlSB.append(")");
      }
    }
    //    for (int i=0;i<SecurityPrincipalContext.getUserDetails().getAuthorities().size();i++){
    //      SecurityPrincipalContext.getUserDetails().getAuthorities().
    //      sqlSB.append()
    //    }
    List<SysRoleEntity> roleList = sysRoleRepository.list(SysRoleEntity.class, sqlSB.toString());
    for (SysRoleEntity sysRoleEntity : roleList) {
      sysRoleRepository.findTreeRole(sysRoleEntity);
    }

    sqlSB.setLength(0);
    sqlSB.append("select menuId from SysRoleMenuEntity where roleId in(");
    for (int i = 0; i < roleList.size(); i++) {
      sqlSB.append("'").append(roleList.get(i).getId()).append("'");
      if (i != roleList.size() - 1) {
        sqlSB.append(",");
      } else {
        sqlSB.append(")");
      }
    }
    List<String> menuIdList = sysRoleRepository.list(String.class, sqlSB.toString());
    Map<String, Object> map = new HashMap<>();
    map.put("menuIdList", menuIdList);
    sqlSB.setLength(0);
    sqlSB.append(
        "select d.* from "
            + EntityUtil.getSqlTableName(sysMenuRepository.getClazz())
            + " d where d.isDelete=false and d.status=1 and d.id in(:menuIdList)");
    List<SysMenuEntity> sysMenuEntities = sysMenuRepository.findByNativeQuery(sqlSB.toString(), map);
    //查询菜单在登录权限下的所有权限
    for (SysMenuEntity sysMenuEntity : sysMenuEntities) {
      for (SysRoleEntity roleEntity : roleList) {
        TreeSet<SysRoleEntity> childRoles = roleEntity.getChildren();
        //菜单在登录权限下所有权限
        menuSetRole(sysMenuEntity, childRoles);
        if (sysMenuEntity.getSysRoleList() != null) {
          List<SysRoleEntity> copySysRoleEntity = new ArrayList<>();
          copySysRoleEntity.addAll(sysMenuEntity.getSysRoleList());
          //对菜单在登录权限下的所有权限进行划分级，分级set在SysRole
          TreeSet<SysRoleEntity> sysRoleEntities = UpDownTreeEntityServiceImpl.createUpDownTreeEntityService(SysRoleEntity.class).upDownTreeEntity(copySysRoleEntity);
          copySysRoleEntity.clear();
          for (SysRoleEntity sysRoleEntity : sysRoleEntities) {
            copySysRoleEntity.add(sysRoleEntity);
          }
          sysMenuEntity.setSysRoleList(copySysRoleEntity);
        }
//        SysRoleEntity.setChildRoles(sysMenuEntity.get);
        //        if (childRoles != null && childRoles.size() > 0) {
//          for (SysRoleEntity sysRoleEntity : childRoles) {
//            SysRoleMenuEntity sysRoleMenuEntity = sysMenuRepository.findMiddleTable(SysRoleMenuEntity.class, "roleId", sysRoleEntity.getId(), "menuId", sysMenuEntity.getId());
//            if (sysRoleMenuEntity != null) {
//              if (sysMenuEntity.getSysRoleList() == null) {
//                sysMenuEntity.setSysRoleList(new ArrayList<SysRoleEntity>());
//              }
//              sysMenuEntity.getSysRoleList().add(sysRoleEntity);
//            }
//          }
//        }
      }
    }
    UpDownTreeEntityService<SysMenuEntity> upDownTreeEntityService = UpDownTreeEntityServiceImpl.createUpDownTreeEntityService(SysMenuEntity.class);
    return upDownTreeEntityService.upDownTreeEntity(sysMenuEntities);
  }

  //设置菜单所有权限不分权限级别
  private void menuSetRole(SysMenuEntity sysMenuEntity, TreeSet<SysRoleEntity> childRoles) {
    if (childRoles != null && childRoles.size() > 0) {
      for (SysRoleEntity sysRoleEntity : childRoles) {
        SysRoleMenuEntity sysRoleMenuEntity = sysMenuRepository.findMiddleTable(SysRoleMenuEntity.class, "roleId", sysRoleEntity.getId(), "menuId", sysMenuEntity.getId());
        if (sysRoleMenuEntity != null) {
          if (sysMenuEntity.getSysRoleList() == null) {
            sysMenuEntity.setSysRoleList(new ArrayList<SysRoleEntity>());
          }
          sysMenuEntity.getSysRoleList().add(sysRoleEntity);
        }
        menuSetRole(sysMenuEntity, sysRoleEntity.getChildren());
      }
    }
  }

  /**
   * 挪动菜单到其他菜单下面需要限制在该菜单原本的权限下 除了顶级权限账户可以做本级菜单修改外其他权限账户只能做下级菜单修改 前端传过来默认是该菜单在当前登陆者的权限
   * 如果没有传权限id则是去掉该菜单在当前登陆者的所有权限 将修改权限List集合跟save同样做树形排序，获得该排序后的树形TreeSet顶级权限查询数据库是否一致
   *
   * @param sysMenuDto
   * @return
   */
  @Override
  public JsonResult update(InsertUpdSysMenuDto sysMenuDto) {
    SysMenuEntity menu = sysMenuRepository.findById(SysMenuEntity.class, sysMenuDto.getId());
    if (menu == null) {
      return JsonResult.putFail("菜单获取失败");
    }
    List<SysMenuEntity> existMenuList = sysMenuRepository.findByFiled("url", sysMenuDto.getUrl());
    if (existMenuList.size() != 0) {
      return JsonResult.putFail("已经存在该" + sysMenuDto.getUrl() + "菜单，更新失败");
    }
    // 顶级权限拥有所有菜单，更新菜单的上级菜单必须是原权限下的菜单
    // 比如有个菜单的权限不是本登录者的权限,那么更新菜单的上级菜单就不能为该菜单，
    // 菜单上级还要判断不能为下级
    Timestamp updTime = new Timestamp(System.currentTimeMillis());
    List<String> roleIdList = sysMenuDto.getRoleIdList();
    Map<String, Object> paramMap = new HashMap<>();
    List<String> roleNameList = new ArrayList();
    JsonResult jsonResult = null;
    List<SysRoleEntity> userRoleList = sysUserRepository.userGetRoleList(paramMap, roleNameList);
    // 先对权限排序，再依次检测其上级菜单是否有权限
    jsonResult = menuParentIdSafe(null, userRoleList);
    if (jsonResult != null) {
      return jsonResult;
    }
    menu.setParentId(sysMenuDto.getParentId());
    menu.setUrl(sysMenuDto.getUrl());
    menu.setName(sysMenuDto.getName());
    // 顶级权限向下存储
    TreeSet<SysRoleEntity> underMaxRoleSet = new TreeSet<>();
    if (roleIdList != null && roleIdList.size() != 0) {
      jsonResult = checkParamBySaveOrUpdMenu(roleIdList, underMaxRoleSet, userRoleList);
      if (jsonResult != null) {
        return jsonResult;
      }
    }
    //    对前端没有传进来的权限即是需要删掉的权限进行处理
    List<SysRoleEntity> userRoleNoRemove = new ArrayList<>();

    SysRoleEntity adminRole = null;
    if (underMaxRoleSet.size() == 1
            && underMaxRoleSet.iterator().next().getName().equals(SysConstants.PROJECT_ROLE_ADMIN.getValue())) {
      adminRole = underMaxRoleSet.iterator().next();
      userRoleNoRemove.add(adminRole);
    } else {
      underMaxRole:
      for (SysRoleEntity underMaxRole : underMaxRoleSet) {
        for (SysRoleEntity userRole : userRoleList) {
          if (underMaxRole.getParentId().equals(userRole.getId())) {
            userRoleNoRemove.add(userRole);
            continue underMaxRole;
          }
        }
      }
    }
    userRoleList.removeAll(userRoleNoRemove);

    //      处理需要删除的一整个树形权限的菜单
    if (userRoleList.size() != 0) {
      //      if (userRoleList.size() != 1 && userRoleList.get(0).getLevel() != 0) {
      for (SysRoleEntity userRole : userRoleList) {
        //        查询role_menu中间表是否该登陆者权限拥有该资源，
        // 有则需要以该登陆者权限作为树根自顶向下删除拥有该资源的整个树形权限
        //        查询中间表有则删除并查询下一权限

        //  递归：下一权限中间表有关联继续删除并查询下一权限，退出条件下一权限没有中间表关联或者没有下一权限
        //        userRole
        SysRoleMenuEntity roleMenu =
            (SysRoleMenuEntity)
                sysMenuRepository.findMiddleTable(
                    SysRoleMenuEntity.class,
                    "roleId",
                    userRole.getId(),
                    "menuId",
                    sysMenuDto.getId());
        // 登录者有权限才能删除其下级权限的资源
        if (roleMenu != null) {
          List<SysRoleEntity> underSecondMaxRoleList =
              sysMenuRepository.findByFiled(SysRoleEntity.class, "parentId", userRole.getId());
          for (SysRoleEntity underSecondMaxRole : underSecondMaxRoleList) {
            deleteRoleMenuByRoleTree(underSecondMaxRole.getId(), sysMenuDto.getId());
          }
        }
      }
      //        如果删除超级管理员对该菜单的权限，
      // 那么超级管理员无法访问该菜单也就无法对该菜单进行再次update
      //        应该在del操作下可以删除整个菜单以及菜单所有权限，
      // 这里的update不允许删除超级管理员对该菜单拥有的权限，以便能继续修改该菜单信息
    }
    if (underMaxRoleSet.size() > 0) {
      //    调整该菜单权限为当前树形权限，去掉不在underMaxRoleSet树形权限中的权限，
      // 加入树形underMaxRoleSet树形权限中的权限如果存在就不新增

      String sql = "";

      for (SysRoleEntity underMaxRole : underMaxRoleSet) {

        SysRoleMenuEntity roleMenu =
            (SysRoleMenuEntity)
                sysMenuRepository.findMiddleTable(
                    SysRoleMenuEntity.class,
                    "roleId",
                    underMaxRole.getId(),
                    "menuId",
                    sysMenuDto.getId());
        Timestamp createTime = new Timestamp(System.currentTimeMillis());
        if (roleMenu == null) {
          addRoleMenu(sysMenuDto.getId(), underMaxRole.getId(), createTime);
        }
        if (underMaxRole.getParentId() != null) {
          List<SysRoleEntity> roleList =
              sysMenuRepository.findByFiled(
                  SysRoleEntity.class, "parentId", underMaxRole.getParentId());

          roleList.remove(underMaxRole);
          sql =
              "DELETE FROM "
                  + EntityUtil.getSqlTableName(SysRoleMenuEntity.class)
                  + " where roleId in(:roleIdList) and menuId=:menuId";
          paramMap.clear();
          paramMap.put("roleIdList", roleList);
          paramMap.put("menuId", sysMenuDto.getId());
          sysMenuRepository.findByNativeQuery(sql, paramMap, Transformers.ALIAS_TO_ENTITY_MAP);
        }
        addNewDelNotNeedRoleMenu(underMaxRole, sysMenuDto.getId(), createTime);
      }
    }
    sysMenuRepository.update(menu);
    return JsonResult.putSuccess();
  }
}
